/*
 * Copyright 2013 Sigurd Randoll.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.digiway.rapidbreeze.client.controller;

import de.digiway.rapidbreeze.client.infrastructure.BusEvents;
import de.digiway.rapidbreeze.client.infrastructure.ThreadPoolService;
import de.digiway.rapidbreeze.client.model.collector.CollectorModel;
import de.digiway.rapidbreeze.client.model.collector.CollectorModelList;
import de.digiway.rapidbreeze.client.model.collector.LinkBundle;
import de.digiway.rapidbreeze.client.model.collector.UrlInformationResourceService;
import de.digiway.rapidbreeze.client.model.download.DownloadResourceRepository;
import de.digiway.rapidbreeze.shared.rest.url.UrlResource;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.concurrent.Executor;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.cell.PropertyValueFactory;
import org.apache.commons.lang3.Validate;
import org.rribbit.Listener;
import org.rribbit.RRB;

/**
 *
 * @author Sigurd
 */
public class LinkCollectorController implements Initializable {

    @FXML
    private TableView<CollectorModel> tableView;
    @FXML
    private TableColumn<CollectorModel, String> filenameColumn;
    @FXML
    private TableColumn<CollectorModel, String> cloudProviderColumn;
    @FXML
    private TableColumn<CollectorModel, Long> filesizeColumn;
    @FXML
    private TableColumn<CollectorModel, String> statusColumn;
    private UrlInformationResourceService informationResourceService;
    private DownloadResourceRepository downloadResourceRepository;
    private CollectorModelList list;
    private ResourceBundle resourceBundle;
    private Executor executor;
    private static final Logger LOG = Logger.getLogger(LinkCollectorController.class.getName());

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        this.resourceBundle = rb;
        this.list = new CollectorModelList();
        this.tableView.setItems(list);
        this.tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
        this.executor = ThreadPoolService.getQueuedPool();

        this.filenameColumn.setCellValueFactory(new PropertyValueFactory<CollectorModel, String>(CollectorModel.PROP_FILENAME));
        this.cloudProviderColumn.setCellValueFactory(new PropertyValueFactory<CollectorModel, String>(CollectorModel.PROP_CLOUD_PROVIDER));
        this.filesizeColumn.setCellValueFactory(new PropertyValueFactory<CollectorModel, Long>(CollectorModel.PROP_FILESIZE));
        this.statusColumn.setCellValueFactory(new PropertyValueFactory<CollectorModel, String>(CollectorModel.PROP_STATUS));
    }

    void setInformationResourceService(UrlInformationResourceService informationResourceService) {
        this.informationResourceService = informationResourceService;
    }

    void setDownloadResourceRepository(DownloadResourceRepository downloadResourceRepository) {
        this.downloadResourceRepository = downloadResourceRepository;
    }

    @FXML
    private void onClose(ActionEvent event) {
        RRB.get().send(BusEvents.CLOSE_DOWNLOAD_COLLECTOR_WINDOW);
    }

    @Listener(hint = BusEvents.ADD_LINK_BUNDLE)
    public void onAddLinkBundle(LinkBundle linkBundle) {
        for (URL url : linkBundle.getUrls()) {
            CollectorModel model = new CollectorModel(url);
            model.setFilename(resourceBundle.getString("DownloadCollector.GrabbingInformation"));
            if (!list.contains(model)) {
                list.add(model);
            }
        }
        executor.execute(new ResourceChecker(linkBundle.getUrls()));
    }

    @FXML
    private void onRemoveAll(ActionEvent event) {
        list.clear();
        RRB.get().send(BusEvents.CLOSE_DOWNLOAD_COLLECTOR_WINDOW);
    }

    @FXML
    private void onStartAll(ActionEvent event) {
        for (CollectorModel model : new ArrayList<>(list)) {
            startDownload(model.getUrl());
            list.remove(model);
        }
        RRB.get().send(BusEvents.CLOSE_DOWNLOAD_COLLECTOR_WINDOW);
    }

    @FXML
    private void onStartAvailable(ActionEvent event) {
        for (CollectorModel model : new ArrayList<>(list)) {
            if (model.isAvailable()) {
                startDownload(model.getUrl());
                list.remove(model);
            }
        }
        list.clear();
        RRB.get().send(BusEvents.CLOSE_DOWNLOAD_COLLECTOR_WINDOW);
    }

    private void startDownload(String url) {
        executor.execute(new DownloadLauncher(url));
    }

    private class DownloadLauncher implements Runnable {

        private String url;

        public DownloadLauncher(String url) {
            this.url = url;
        }

        @Override
        public void run() {
            try {
                downloadResourceRepository.addDownload(url);
            } catch (RuntimeException ex) {
                LOG.log(Level.SEVERE, "An exception occured during launching a new download for url:" + url, ex);
            }
        }
    }

    private class ResourceChecker implements Runnable {

        private List<URL> urlsToCheck;

        public ResourceChecker(List<URL> urlsToCheck) {
            Validate.notNull(list);
            this.urlsToCheck = urlsToCheck;
        }

        @Override
        public void run() {
            try {
                for (URL url : urlsToCheck) {
                    UrlResource urlResource = informationResourceService.getUrlResource(url);
                    list.updateSingleItem(urlResource);
                }
            } catch (RuntimeException ex) {
                LOG.log(Level.SEVERE, "An exception occured during checking status of url resources:" + list, ex);
            }
        }
    }
}
